//本文件是ts泛型工具


/**快速生成指定长度的元组  （固定类型）
 * @template N 长度
 * @template T 数组类型
 * @template Arr 初始数组，一般不填，填了的话长度不可超出N
 * @example
 * 指定长度：type a = TupleOfLength<3>; // [any, any, any]
 * 指定类型：type b = TupleOfLength<2, string>; // [string, string]
 * 填充内容-(意义不大)：type c = TupleOfLength<3, string, [number]>; // [number, string, string]
 * 可以嵌套-(意义不大)：type d = TupleOfLength<4, string, TupleOfLength<2, number, TupleOfLength<1>>> // [any, number, string, string] 
 */
export type TupleOfLength<N extends number, T = any, Arr extends any[] = []> = Arr['length'] extends N ? Arr : TupleOfLength<N, T, [...Arr, T]>; //通过递归生成

/**ts加法 A + B
 * @example
 * type a = Add<1, 1> // type a = 2
 * type b = Add<100, 2> // type b = 102
 */
export type Add<A extends number, B extends number> = [...TupleOfLength<A>, ...TupleOfLength<B>]['length']

/**ts减法 A - B
 * @example
 * type a = Sub<4, 1> // type a = 3
 * type b = Sub<100, 2> // type b = 98
 */
export type Sub<A extends number, B extends number> =
    TupleOfLength<A> extends [...infer Res, ...TupleOfLength<B>] //利用 infer 关键字，拿到 A-B 对应长度的元组 Res
    ? Res['length'] : never;

/**生成 指定范围(闭区间)  整数类型的 ts定义
 * @template Start 整数的开始位置，范围 >= 0  
 * @template End 整数的结束位置，范围 >= Start  
 * @template Arr 运行时所用的数组，别填
 * @example
 * 基础 0~n type a = IntUnion<0, 3>;  // 0 | 1 | 2 | 3
 * 特殊 m~n type b = IntUnion<1, 4>;  //  1 | 2 | 3 | 4
 * @tip 当数字比较多时，鼠标悬浮查看的数字可能不是按顺序的，但是类型是正确的 IntUnion<0,100>，悬浮发现得到的结果末尾是99，但是实际上100藏在中间）
 */
export type IntUnion<Start extends number, End extends number, Arr extends any[] = TupleOfLength<Start>> =
    Arr['length'] extends End
    ? Start | End //最后补上End，实现闭区间
    : IntUnion<Start | Arr['length'], End, [any, ...Arr]>; //通过递归，从0~N，依次增加并获取数组长度，然后添加到R中，实现0~N的联合类型

